#ifndef SGU_TEMPLATE_H
#define SGU_TEMPLATE_H

SGU_NS_BEGIN

//! Sign
/*! -1 or 0 or +1 */
template <class T> int sgn(const T & x)
{
 	if (x>0) return 1;
 	if (x<0) return -1;
 	return 0;
}

//! Absolute value by type
template <class T> T absT(const T & x)
{
 	return (x>=0 ? x : -x);
}

//! Square
template <class T> T sqr(const T & x)
{
 	return x * x;
}

//! Exchange
template <class T> void xchg(T & a, T & b)
{
 	T c;
 	c=a,a=b,b=c;
}

#if 0
template <class T> T& minR(T& a , T& b)
{
	return ((a<=b) ? a : b);
}

template <class T> T& maxR(T& a , T& b)
{
	return ((a>=b) ? a : b);
}

template <class T> const T& minR(const T& a , const T& b)
{
	return ((a<=b) ? a : b);
}

template <class T> const T& maxR(const T& a , const T& b)
{
	return ((a>=b) ? a : b);
}

template <class T> T minT(T a , T b)
{
	return ((a<=b) ? a : b);
}

template <class T> T maxT(T a , T b)
{
	return ((a>=b) ? a : b);
}


template <class T> void setMin(T& a, T b)
{
	if(b<a) a=b;
}

template <class T> void setMax(T& a, T b)
{
	if(b>a) a=b;
}

#endif


template <> real absT(const real & x);
         

template <class T> void constructor(T * ptr)
{
	::new(ptr) T();
}

template <class T> void constructor(T * ptr, const T & a)
{
	::new(ptr) T(a);
}

template <class T> void destructor(T * ptr)
{
	ptr->~T();
}

template <class T> T * nil()
{
	return (T*)NULL;
}

template <class T> const T * cnil()
{
	return (const T*)NULL;
}

template <typename T, typename C=T> class Minimal
{
	private:
	T _value;
	bool _init;

	public:
	Minimal() : _init(false) {}
	void operator &=(C x) {_value = _init ? (_value <? x) : x; _init=true;}
	operator C () const {if(!_init) THROWSGUEXCEPTION("Empty set"); return _value;}
};	

template <typename T, typename C=T> class Maximal
{
	private:
	T _value;
	bool _init;

	public:
	Maximal() : _init(false) {}
	void operator &=(C x) {_value = _init ? (_value >? x) : x; _init=true;}
	operator C () const {if(!_init) THROWSGUEXCEPTION("Empty set"); return _value;}
};	



template <typename T> bool inoo(T x, T a, T b)
{
	return (x> a)&&(x< b);
}

template <typename T> bool inco(T x, T a, T b)
{
	return (x>=a)&&(x< b);
}

template <typename T> bool inoc(T x, T a, T b)
{
	return (x> a)&&(x<=b);
}

template <typename T> bool incc(T x, T a, T b)
{
	return (x>=a)&&(x<=b);
}


SGU_NS_END

#endif
